import * as THREE from '../../../../modules/three/three.module.js'

const _axis = /*@__PURE__*/ new THREE.Vector3();


// 方位指示器
class OrientationHelper extends THREE.Object3D {
  orient = new THREE.Vector3();
  // dir is assumed to be normalized

  constructor(
    showBaseLine,
    dir = new THREE.Vector3(0, 0, 1),
    origin = new THREE.Vector3(0, 0, 0),
    length = 1,
    color = 0xffff00,
    headLength = length * 0.1,
    headWidth = headLength * 0.7,
  ) {
    super();

    let _lineGeometry, _coneGeometry, _lineGeometry2;
    this.type = 'ArrowHelper';

    if (_lineGeometry === undefined) {
      _lineGeometry = new THREE.BufferGeometry();
      _lineGeometry.setAttribute(
        'position',
        new THREE.Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3),
      );
      if (showBaseLine) {
        _lineGeometry2 = new THREE.BufferGeometry();
        _lineGeometry2.setAttribute(
          'position',
          new THREE.Float32BufferAttribute([-50, 0, 0, 50, 0, 0], 3),
        );
      }

      _coneGeometry = new THREE.CylinderGeometry(0, 0.5, 1, 7, 1);
      _coneGeometry.translate(0, -0.5, 0);
    }

    this.position.copy(origin);

    this.line = new THREE.Line(
      _lineGeometry,
      new THREE.LineBasicMaterial({
        color: color,
        toneMapped: false,
        depthTest: false,
        depthWrite: false,
        transparent: true,
      }),
    );
    this.line.matrixAutoUpdate = false;
    this.add(this.line);

    if (showBaseLine) {
      this.line2 = new THREE.Line(
        _lineGeometry2,
        new THREE.LineBasicMaterial({
          color: color,
          toneMapped: false,
          depthTest: false,
          depthWrite: false,
          transparent: true,
        }),
      );
      this.line2.matrixAutoUpdate = false;
      this.add(this.line2);
    }

    this.cone = new THREE.Mesh(
      _coneGeometry,
      new THREE.MeshBasicMaterial({
        color: color,
        toneMapped: false,
        depthTest: false,
        depthWrite: false,
        transparent: true,
      }),
    );
    this.cone.matrixAutoUpdate = false;
    this.add(this.cone);

    this.setDirection(dir);
    this.setLength(length, headLength, headWidth);
  }

  setDirection(dir) {
    this.orient.copy(dir);
    // dir is assumed to be normalized

    if (dir.y > 0.99999) {
      this.quaternion.set(0, 0, 0, 1);
    } else if (dir.y < -0.99999) {
      this.quaternion.set(1, 0, 0, 0);
    } else {
      _axis.set(dir.z, 0, -dir.x).normalize();

      const radians = Math.acos(dir.y);

      this.quaternion.setFromAxisAngle(_axis, radians);
    }
  }

  setLength(length, headLength = length * 0.2, headWidth = headLength * 0.2) {
    this.line.scale.set(1, Math.max(0.0001, length - headLength), 1); // see #17458
    this.line.updateMatrix();

    this.cone.scale.set(headWidth, headLength, headWidth);
    this.cone.position.y = length;
    this.cone.updateMatrix();
  }

  setColor(color) {
    this.line.material.color.set(color);
    this.cone.material.color.set(color);
  }

  copy(source) {
    super.copy(source, false);

    this.line.copy(source.line);
    this.cone.copy(source.cone);

    return this;
  }

  convertToArrowHeler(color = '#0ff') {
    const arrowHelper = new THREE.ArrowHelper();
    arrowHelper.line.geometry.copy(this.line.geometry);
    arrowHelper.cone.geometry.copy(this.cone.geometry);
    arrowHelper.position.copy(this.position);
    arrowHelper.quaternion.copy(this.quaternion);
    arrowHelper.setColor(color);
    arrowHelper.orient = new THREE.Vector3().copy(this.orient);
    arrowHelper.line.material.depthTest = false;
    arrowHelper.line.material.depthWrite = false;
    arrowHelper.cone.material.depthTest = false;
    arrowHelper.cone.material.depthWrite = false;
    return arrowHelper;
  }
}

export { OrientationHelper };
